﻿using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using Volo.Abp.DependencyInjection;

namespace LeoGemini.Service.Infrastructure.Security.Authentication.JwtBearer
{
    public class TokenBuilder : ITokenBuilder, ITransientDependency
    {
        private readonly JwtAuthorizationRequirement _jwtAuthorizationRequirement;

        public TokenBuilder(
            JwtAuthorizationRequirement jwtAuthorizationRequirement)
        {
            _jwtAuthorizationRequirement = jwtAuthorizationRequirement;
        }

        public Token BuildJwtToken(Claim[] claims, DateTime? expires = null)
        {
            List<Claim> claimList = new List<Claim>(claims);
            DateTime utcNow = DateTime.UtcNow;

            var jwtSecurityToken = new JwtSecurityToken(
                _jwtAuthorizationRequirement.Issuer, _jwtAuthorizationRequirement.Audience,
                claimList.ToArray(), utcNow, expires,
                _jwtAuthorizationRequirement.SigningCredentials);

            string str = new JwtSecurityTokenHandler().WriteToken(jwtSecurityToken);
            return new Token
            {
                TokenValue = str,
                Expires = expires,
                TokenType = "Bearer"
            };
        }

        public Token BuildJwtToken(
            Claim[] claims,
            DateTime notBefore,
            DateTime? expires = null)
        {
            string str = new JwtSecurityTokenHandler().WriteToken(new JwtSecurityToken(
                _jwtAuthorizationRequirement.Issuer, _jwtAuthorizationRequirement.Audience,
                new List<Claim>(claims).ToArray(), notBefore,
                expires, _jwtAuthorizationRequirement.SigningCredentials));
            return new Token
            {
                TokenValue = str,
                Expires = expires,
                TokenType = "Bearer"
            };
        }

        public Token BuildJwtToken(
            Claim[] claims,
            string ip,
            DateTime? notBefore = null,
            DateTime? expires = null)
        {
            List<Claim> claimList = new List<Claim>(claims) {new(nameof(ip), ip)};

            string str = new JwtSecurityTokenHandler().WriteToken(new JwtSecurityToken(
                _jwtAuthorizationRequirement.Issuer, _jwtAuthorizationRequirement.Audience,
                claimList.ToArray(), notBefore, expires,
                _jwtAuthorizationRequirement.SigningCredentials));
            return new Token
            {
                TokenValue = str,
                Expires = expires,
                TokenType = "Bearer"
            };
        }

        public class Token
        {
            public string TokenValue { get; set; }

            public DateTime? Expires { get; set; }

            public string TokenType { get; set; }
        }
    }
}